﻿using System.Activities.Presentation;
using System.Activities.Presentation.Model;
using System.Activities.Presentation.Services;
using System.Activities.Presentation.View;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;

namespace Headsight.BPMN2WF.WF.Impl
{
    /// <summary>
    /// Temporary class for very early / former prototype WF beautifier code.
    /// </summary>
    public static class ModelBeautifier
    {
        public static void Connect(ModelItem parent, ViewStateService viewStateService, ViewService activityDesignerViewService)
        {
            var parentShapeLocation = (Point)viewStateService.RetrieveViewState(parent, "ShapeLocation");
            var parentShapeSize = (Size)viewStateService.RetrieveViewState(parent, "ShapeSize");

            var parentModelItemSoR = new ModelItemUtils(parent, activityDesignerViewService);
            var childs = parentModelItemSoR.ImmediateChilds;

            var pointCollections = new List<PointCollection>();
            foreach (var each in childs)
            {
                CalculatePosition(each, childs, parentShapeLocation, parentShapeSize, activityDesignerViewService, viewStateService);
                pointCollections.Add(CalculateConnector(each, childs, parentShapeLocation, parentShapeSize, activityDesignerViewService, viewStateService));
            }

            if (pointCollections.Count == 1)
            {
                viewStateService.StoreViewStateWithUndo(parent, "ConnectorLocation", pointCollections[0]);
            }
            else if (pointCollections.Count == 2)
            {
                viewStateService.StoreViewStateWithUndo(parent, "TrueConnector", pointCollections[0]);
                viewStateService.StoreViewStateWithUndo(parent, "FalseConnector", pointCollections[1]);
            }

            foreach (var each in childs)
            {
                Connect(each, viewStateService, activityDesignerViewService);
            }
        }

        private static void CalculatePosition(ModelItem child, IList<ModelItem> childs, Point parentLocation, Size parentSize,
                ViewService viewService, ViewStateService viewStateService)
        {
            if (childs.Count != 1) return;

            var childModelItemSoR = new ModelItemUtils(child, viewService);
            var childModelItemView = childModelItemSoR.View;

            var currentLocation = (Point)viewStateService.RetrieveViewState(child, "ShapeLocation");
            var currentSize = (Size)viewStateService.RetrieveViewState(child, "ShapeSize");

            var mItem_view_wfvelem = childModelItemView as WorkflowViewElement;

            var actHeight = mItem_view_wfvelem.ActualHeight;
            var actWidth = mItem_view_wfvelem.ActualWidth;

            var center = parentLocation.X + parentSize.Width / 2;
            var bottom = parentLocation.Y + parentSize.Height;

            //var anchorY = 30 + bottom;
            var anchorX = center - actWidth / 2;

            viewStateService.StoreViewStateWithUndo(child, "ShapeLocation", new Point(anchorX, currentLocation.Y));
            //viewStateService.StoreViewStateWithUndo(child, "ShapeSize", new Size(actWidth, actHeight));
        }

        private static PointCollection CalculateConnector(ModelItem child, IList<ModelItem> childs, Point parentLocation, Size parentSize, 
            ViewService viewService, ViewStateService viewStateService)
        {
            var pointCollection = new PointCollection();

            var eachModelItemSoR = new ModelItemUtils(child, viewService);

            FrameworkElement view = eachModelItemSoR.View;

            var eachLocation = (Point)viewStateService.RetrieveViewState(child, "ShapeLocation");

            var eachWidth = view.ActualWidth;
            var eachHeight = view.ActualHeight;

            var pX = parentLocation.X + parentSize.Width / 2;
            var pY = parentLocation.Y + parentSize.Height;

            var x = eachLocation.X + eachWidth / 2;
            var y = eachLocation.Y;

            if (childs.Count == 1)
            {
                var halfY = pY + ((y - pY) / 2);
                pointCollection.Add(new Point(pX, pY));
                pointCollection.Add(new Point(pX, halfY));
                pointCollection.Add(new Point(x, halfY));
                pointCollection.Add(new Point(x, y));
            }
            if (childs.Count == 2 && child == childs[0])
            {
                pointCollection.Add(new Point(parentLocation.X, parentLocation.Y + parentSize.Height / 2));
                pointCollection.Add(new Point(x, parentLocation.Y + parentSize.Height / 2));
                pointCollection.Add(new Point(x, y));
            }
            else if (childs.Count == 2 && child == childs[1])
            {
                pointCollection.Add(new Point(parentLocation.X + parentSize.Width, parentLocation.Y + parentSize.Height / 2));
                pointCollection.Add(new Point(x, parentLocation.Y + parentSize.Height / 2));
                pointCollection.Add(new Point(x, y));
            }

            return pointCollection;
        }

        public static void FixFlow(WorkflowDesigner wfDesigner)
        {
            var modelService = wfDesigner.Context.Services.GetService<ModelService>();
            var viewStateService = wfDesigner.Context.Services.GetService<ViewStateService>();

            var flowChartItem = modelService.Root.Properties["Implementation"].Value;

            var activityDesigner = flowChartItem.View as ActivityDesigner;
            var activityDesignerViewService = activityDesigner.Context.Services.GetService<ViewService>();


            //using (ModelEditingScope scope = mItem_flowchart.BeginEdit())
            {
                //
                // Set Flowchart's start shape location and size:
                //
                viewStateService.StoreViewStateWithUndo(flowChartItem, "ShapeLocation", new Point(270, 2.5));
                viewStateService.StoreViewStateWithUndo(flowChartItem, "ShapeSize", new Size(60, 75));

                ModelItem prev = flowChartItem;

                if (true)
                {
                    Connect(prev, viewStateService, activityDesignerViewService);
                }
            }
        }
    }
}
